package com.dx.wx.util;

import com.github.binarywang.wxpay.v3.util.PemUtils;
import okhttp3.HttpUrl;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;

import okhttp3.HttpUrl;

import java.security.Signature;
import java.util.Base64;

public class WxPayUtil {


    // Authorization: <schema> <token>
// GET - getToken("GET", httpurl, "")
// POST - getToken("POST", httpurl, json)
//    String schema = "WECHATPAY2-SHA256-RSA2048";


    public static String getToken(String pKeyPath, String mchId, String cerNo, String nonceStr, String method, String httpUrl, String body) throws Exception {
        HttpUrl url = HttpUrl.parse(httpUrl);
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, url, timestamp, nonceStr, body);
        String signature = sign(mchId, message.getBytes("utf-8"), pKeyPath);

        return "mchid=\"" + mchId + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + cerNo + "\","
                + "signature=\"" + signature + "\"";
    }

    /**
     * 获取私钥。
     *
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey(String filename) throws IOException {

        String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }

    //获取授权
    public static String getAuthorization(String token) {
        String schema = "WECHATPAY2-SHA256-RSA2048";
        return schema + " " + token;
    }

    private static String sign(String mchId, byte[] message, String pKeyPath) throws Exception {
        FileInputStream certStream = new FileInputStream(pKeyPath);
        char[] password = mchId.toCharArray();
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(certStream, password);
        //alias 默认为 tenpay certificate
        PrivateKey privateKey = (PrivateKey) ks.getKey(ks.aliases().nextElement(), password);
//        PrivateKey privateKey = getPrivateKey(pKeyPath);
//        PrivateKey privateKey = PemUtils.loadPrivateKey(new FileInputStream(pKeyPath));
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(privateKey);
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    private static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
            canonicalUrl += "?" + url.encodedQuery();
        }

        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

}
